//
// Created by martin on 3/22/22.
//

#ifndef MUDUO_FTPCONTEXT_H
#define MUDUO_FTPCONTEXT_H

#include "FtpRequest.h"
#include "FtpSession.h"
#include "muduo/base/noncopyable.h"
#include "muduo/base/Timestamp.h"
#include "muduo/net/Buffer.h"
#include "muduo/net/InetAddress.h"
#include "IdleConnectionEntry.h"

#include <map>
#include <memory>

namespace ftp
{

//class Buffer;
class UserDao;

/**
 * Ftp上下文, 保存与本次连接有关的Ftp信息
 * @details 非线程安全, 被TcpConnection对象持有, 只能在所属IO线程被访问.
 */
class FtpContext : public muduo::noncopyable,
	std::enable_shared_from_this<FtpContext>
{
public:
	enum FtpRequestParseState
	{
		kExpectRequestLine = 0,
		kExpectCommand,
		kExpectParam,
		kGotAll
	};

	FtpContext(muduo::net::EventLoop* loop, const muduo::net::TcpConnectionPtr& ctrlConn, const WeakIdleConnectionEntryPtr& weakEntryPtr, const UserDao& ftpUserDao);
	~FtpContext();

	bool parseRequest(muduo::net::Buffer* buffer, muduo::Timestamp receiveTime);
	void resetRequest()
	{
		state_ = kExpectRequestLine;
		FtpRequest dummy;
		oldRequest_.swap(request_);
		request_.swap(dummy);
	}

	bool gotAll() const
	{
		return state_ == kGotAll;
	}

	void startFtpSession();

	void handleFtpCommand();

	size_t numErrors() const
	{
		return numErrors_;
	}

	void increaseError()
	{
		++numErrors_;
	}

	void clearError()
	{
		numErrors_ = 0;
	}

	FtpRequest& request()
	{
		return request_;
	}

	const WeakIdleConnectionEntryPtr& weakIdleConnectionEntryPtr() const
	{
		return weakEntryPtr_;
	}

	static const size_t kNumErrorsMax = 30;

private:
	bool doRequestLine(const char* begin, const char* end);

	muduo::net::TcpConnectionWeakPtr controlConnWeakPtr_;

	muduo::net::EventLoop* loop_;
	muduo::net::InetAddress peerAddr_;
	size_t numErrors_;
	FtpRequestParseState state_;
	FtpRequest request_;
	FtpRequest oldRequest_;
	std::shared_ptr<FtpSession> session_; // for shared_from_this()

	const WeakIdleConnectionEntryPtr weakEntryPtr_;
};

typedef std::shared_ptr<FtpContext> FtpContextPtr;
typedef std::weak_ptr<FtpContext>   FtpContextWeakPtr;

} // namespace ftp

#endif //MUDUO_FTPCONTEXT_H
